/******************************************************************************
 * Copyright (C) 2015  671643387@qq.com
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 *****************************************************************************/

#ifndef NODE_DB_RDB_CALLBACK_H_
#define NODE_DB_RDB_CALLBACK_H_

#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif


namespace node {
    namespace db {
		class ResultSet;

        ///////////////////////////////////////////////////////////////////////
        template<class Class, typename ParamType1, typename ParamType2>
        class _Callback
        {
        protected:
            typedef void (Class::*Method)(ParamType1, ParamType2);
            Class* object_;
            Method method_;
            ParamType1 param1_;
            ParamType2 param2_;
            void execute_() { (object_->*method_)(param1_, param2_); }

        public:
            _Callback(Class* object, Method method, ParamType1 param1, ParamType2 param2)
                : object_(object), method_(method),
                  param1_(param1), param2_(param2)
            {
            }

            _Callback(_Callback<Class, ParamType1, ParamType2> const& cb)
                : object_(cb.object_), method_(cb.method_),
                  param1_(cb.param1_), param2_(cb.param2_)
            {
            }
        };

        //template<class Class, typename ParamType1>
        //class _Callback
        //{
        //protected:
        //    typedef void (Class::*Method)(ParamType1);
        //    Class* object_;
        //    Method method_;
        //    ParamType1 param1_;
        //    void execute_() { (object_->*method_)(param1_); }
        //
        //public:
        //    _Callback(Class* object, Method method, ParamType1 param1)
        //        : object_(object), method_(method),
        //        param1_(param1)
        //    {
        //    }
        //
        //    _Callback(_Callback<Class, ParamType1> const& cb)
        //        : object_(cb.object_), method_(cb.method_),
        //        param1_(cb.param1_)
        //    {
        //    }
        //};
		
        ///////////////////////////////////////////////////////////////////////
		class IQueryCallback
		{
		public:
			virtual void execute() = 0;
			virtual ~IQueryCallback() {}

			virtual void setResult(ResultSet* result) = 0;
			virtual ResultSet* getResult() = 0;
		};

        template<class CB>
        class _IQueryCallback : public CB, public IQueryCallback
        {
        public:
            _IQueryCallback(CB const& cb) : CB(cb)
            {
            }

            void execute() { CB::execute_(); }
            void setResult(ResultSet* result) { CB::param1_ = result; }
            ResultSet* getResult() { return CB::param1_; }
        };

        ///////////////////////////////////////////////////////////////////////
        template<class Class, typename ParamType1>
        class QueryCallback : public _IQueryCallback<_Callback<Class, ResultSet*, ParamType1> >
        {
        private:
            typedef _Callback<Class, ResultSet*, ParamType1> QC1;

        public:
            QueryCallback(Class* object, typename QC1::Method method, ResultSet* result, ParamType1 param1)
                : _IQueryCallback<QC1>(QC1(object, method, result, param1))
            {
            }
        };
    }
}

#endif // NODE_DB_RDB_CALLBACK_H_
